import ij.IJ;
import ij.ImagePlus;
import ij.gui.NewImage;
import ij.plugin.PlugIn;
import ij.process.ImageProcessor;


import java.awt.Color;


import java.awt.Font;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.PrintStream;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.InputMismatchException;
import java.util.Locale;
import java.util.Scanner;

import pluginUtils.Doublet;
import pluginUtils.Punkt;
import pluginUtils.Quadrilatere;
import pluginUtils.Transformation;


// Read a datafile and a image file, compute the distorted image 
// for anamorphosis inside a cylinder
// the mirror is paroboloidal concave
// Computing the inverse of y



public class AnamorphConeInverseAuFondAnalyticReverseFunction extends ImagePlus implements PlugIn{
	{Locale.setDefault(Locale.US); }
	
	
	
	private ImageProcessor primeIP; 
	private int X=2800,Y=2100; // image size
	
	private ImagePlus inverted;  
	private ImageProcessor inv_ip;  
	private static boolean windows=false; 
	
	
	
	
	
	// For the scaling of the image
	private double x0=0,x1=1,y0=0,y1=1;
	private double acoef,ccoef,vcoef,wcoef; 
	
	


	public void setCoefs(){
		acoef=X/(x1-x0); 
		vcoef=Y/(y1-y0); 
		ccoef=-acoef*x0; 
		wcoef=-vcoef*y0; 
	}
	
	
	
	
	public void setBounds(double xl,double xu,double yl,double yu){
		x0=xl; 
		x1=xu;
		y0=yl;
		y1=yu;
		 
	}
	
	private void drawPoint(Punkt p){
		double xCenter=p.getY(); 
		double yCenter=p.getZ(); 
		int intX=(int)(xCenter*acoef+ccoef);
		int intY=(int)(yCenter*vcoef+wcoef);
		primeIP.fillOval(intX-10,intY-10,20,20);
	}
	private void drawPoint(Punkt p,ImageProcessor toto){
		double xCenter=p.getY(); 
		double yCenter=p.getZ(); 
		int intX=(int)(xCenter*acoef+ccoef);
		int intY=(int)(yCenter*vcoef+wcoef);
		System.out.println(intX+" ** "+intY);
		toto.fillOval(intX-5,intY-5,10,10);
	}
	
	private void drawLine(double xd,double yd,double xf,double yf,ImageProcessor toto){
		int XD=(int)(xd*acoef+ccoef); 
		int YD=(int)(yd*vcoef+wcoef); 
		int XF=(int)(xf*acoef+ccoef); 
		int YF=(int)(yf*vcoef+wcoef);
		//System.out.println("---->"+XD+" "+YD+" "+XF+" "+YF); 
		toto.drawLine(XD,YD,XF,YF); 
	}
	
	
	private void drawLine(Punkt A,Punkt B,ImageProcessor toto){
		drawLine(A.getY(),A.getZ(),B.getY(),B.getZ(),toto); 
	}
	
	private void drawLine(double xd,double yd,double xf,double yf){
		int XD=(int)(xd*acoef+ccoef); 
		int YD=(int)(yd*vcoef+wcoef); 
		int XF=(int)(xf*acoef+ccoef); 
		int YF=(int)(yf*vcoef+wcoef);
		//System.out.println("---->"+XD+" "+YD+" "+XF+" "+YF); 
		primeIP.drawLine(XD,YD,XF,YF); 
	}
	
	private void drawLine(Punkt A,Punkt B){
		drawLine(A.getY(),A.getZ(),B.getY(),B.getZ()); 
	}
	
	
	
	
	
	public void run(String arg) {
		System.out.println("go");
		
		ImagePlus imp; 
		if(!windows)
		 imp = IJ.openImage("/tmp/monalisa.jpg");
		else
		imp=IJ.openImage("F:/Povray/anamorphoses/mona.png");
		
		//ImagePlus imp=IJ.openImage("F:/Povray/anamorphoses/Mona_Lisa.png");
		//ImagePlus imp=IJ.openImage("C:/Documents and Settings/Francesco/Mes documents/Mona_Lisacarre.png");

		imp.setTitle("PrimeIP");
		
	
		System.out.println(imp); 
		primeIP=imp.getProcessor();
		X=primeIP.getWidth(); 
		Y=primeIP.getHeight(); 
		
        setStack(null, imp.getStack());
        setCalibration(imp.getCalibration()); 
		
        	show();
		
		
		

		

		
		primeIP.setFont(new Font(null,Font.ITALIC,60));
		primeIP.setColor(Color.RED);
		primeIP.setLineWidth(10); 
	
		setProcessor("Verifying", primeIP);
		
		
		
		 
		
             
          // create a new image of size (2h)*(2piR)
		int W=2000; 
		int H=2000; 
 			inverted = NewImage.createRGBImage ("monamod",W,H, 1, NewImage.FILL_WHITE);
   
             
 			inv_ip = inverted.getProcessor();
 			
 			for(int i=0;i<inverted.getWidth();i++)
 				for(int j=0;j<inverted.getHeight();j++)
 					inv_ip.putPixel(i,j,0xFFFFFF); 
     
 			System.out.println("toto");
 			
 			// cone radius
 			double l=3; 
 			// height of the cone
 			double h=4; 
 		
 				
 			double umax=0; 
 			double umin=9000; 
 			for(int i=0;i<inv_ip.getWidth();i++){
 				for(int j=0;j<inv_ip.getHeight();j++){
 					double theta=2*Math.PI*(i+0.0)/inv_ip.getWidth(); 
 					theta=theta-Math.PI; 
 					
 					/* Partie a modifier */
 					// tangente angle au sommet du cone
 					double talpha=l/h; 
 					// tangente du double de l'angle au sommet du cone
 					double t2=2*talpha/(1-talpha*talpha); 
 					double t4=(1-t2*t2)/(2*t2); 
 					
 					// y TODO : justifier
 					double fdeU=j*(2.0*Math.PI*l)/W;
 					
 					double valzero=-4.440892098500626E-16; 
 					double u2=1.7146403660926517; 
 					double valu2=2.917120426899504; 
 					double ca=u2/(valu2-valzero);
 					double cb=-ca*valzero; 
 					// En fait, cela devrait s'appeler u
 					double fmoinsundeU=ca*fdeU+cb; 
		
 						/* Fin de la partie a modifier */
 					fmoinsundeU/=l;
 					if(fmoinsundeU>umax)umax=fmoinsundeU;
 					if(fmoinsundeU<umin)umin=fmoinsundeU;
 					//if((fmoinsundeU<1)&&(fmoinsundeU>=0)){
 					int XX=(int)(fmoinsundeU*Math.cos(theta)*primeIP.getWidth()/2); 
 					int YY=(int)(fmoinsundeU*Math.sin(theta)*primeIP.getHeight()/2); 
 					//System.out.println(XX+" "+YY);
 					int col=primeIP.getPixel(XX+primeIP.getWidth()/2,YY+primeIP.getHeight()/2); 
 					inv_ip.putPixel(i,j,col);
 					//} // if
 					}// for k 
 				}// for j
	
 			
        
      System.out.println(umin+" "+umax);
	
		inverted.show();
		
		System.out.println("end !");
	
		
		}
	}	

	